#include "Character.hh"
#include <iostream>

Character::Character(const std::string& name, const std::string& description, unsigned health, unsigned attack, unsigned defense)
    : name(name), description(description), _health(health), maxHealth(health), _attack(attack), _defense(defense) {}


Character::~Character() {
    for (auto item : inventory) {
        delete item;
    }
}

Character::Character(const Character& other) {
    name = other.name;
    description = other.description;
    _health = other._health;
    maxHealth = other.maxHealth;
    _attack = other._attack;
    _defense = other._defense;
    inventory = other.inventory; // Shallow copy, assuming Item has proper copy constructor
}
Character& Character::operator=(const Character& other) {
    if (this != &other) {
        name = other.name;
        description = other.description;
        _health = other._health;
        maxHealth = other.maxHealth;
        _attack = other._attack;
        _defense = other._defense;
        inventory = other.inventory; // Shallow copy, assuming Item has proper copy constructor
    }
    return *this;
}
bool Character::isAlive() const {
    return _health > 0;
}
void Character::setDescription(const std::string& description)  {
    this->description = description;
};
void Character::setMaxHealth(unsigned maxHealth) {
    this->maxHealth = maxHealth;
}
void Character::setName(const std::string& name) {
    this->name = name;
}
void Character::setInventory(const std::vector<Item*>& inventory) {
    this->inventory = inventory;
}
    
bool Character::takeDamage(unsigned damage) {
    std::cout << "Taking " << damage << " damage." << std::endl;
    std::cout << "Health: " << _health << std::endl;
    std::cout << "Defense: " << _defense << std::endl;
    if (damage > _defense&&damage < _health+_defense) {
        std::cout << "1";
        _health -= (damage - _defense);
    }else if (damage > _defense && damage >= _health+_defense){
        std::cout << "2";
        _health = 0;
    }
    return isAlive();
}

bool Character::attack(ICharacter& target) {
    unsigned damage = _attack;
std::cout << "Attacking " << target.getName() << " with " << damage << " damage." << std::endl;

    if (target.takeDamage(damage)) {
        std::cout << target.getName() << " has been attacked." << std::endl;
        return true;
    }
    std::cout << target.getName() << " has survived the attack." << std::endl;
    return false;
}

bool Character::heal(unsigned amount) {
    if (_health + amount > maxHealth) {
        _health = maxHealth;
    } else {
        _health += amount;
    }
    return true;
}
std::string Character::getName() const {
    return name;
}

std::string Character::getDescription() const {
    return description;
}

unsigned Character::getHealth() const {
    return _health;
}

unsigned Character::getMaxHealth() const {
    return maxHealth;
}

unsigned Character::getAttack() const {
    return _attack;
}

unsigned Character::getDefense() const {
    return _defense;
}

std::string Character::toString() const {
    return name + " - HP: " + std::to_string(_health) + "/" + std::to_string(maxHealth);
}

void Character::addToInventory(Item* item) {
    inventory.push_back(item);
    item->applyEffect(*this);
}

void Character::displayInventory() const {
    for (const auto& item : inventory) {
        std::cout << item->getName() << " - " << item->getDescription() << std::endl;
    }
}

void Character::display() const {
    std::cout << name << " - " << description << std::endl;
    std::cout << "HP: " << _health << "/" << maxHealth << std::endl;
    std::cout << "Attack: " << _attack << std::endl;
    std::cout << "Defense: " << _defense << std::endl;
}

void Character::setHealth(unsigned health) {
    _health = health;
}
void Character::addHealth(unsigned health) {
    _health += health;
}
void Character::setAttack(unsigned attack) {
    _attack = attack;
}
void Character::addAttack(unsigned attack) {
    _attack += attack;
}
void Character::addDefense(unsigned defense) {
    _defense += defense;
}
void Character::setDefense(unsigned defense) {
    _defense = defense;
}
std::ostream& operator<<(std::ostream& os, const Character& player) {
    os << "Player: " << player.name << " Description: " << player.description << ". Health: " << player._health << ", Attack: " << player._attack << ", Defense: " << player._defense;
    return os;
}

// += unsigned -> Increase health (addHealth)
Character& Character::operator+=(unsigned health) {
    this->addHealth(health);
    return *this;
}

// += pair<string, unsigned> -> add attack or defense
Character& Character::operator+=(const std::pair<std::string, unsigned>& pair) {
    if (pair.first == "attack") {
        this->addAttack(pair.second);
    } else if (pair.first == "defense") {
        this->addDefense(pair.second);
    }
    return *this;
}

// -= int -> Reduce defense value (modifyDefense)
Character& Character::operator-=(int defense) {
    this->modifyDefense(-defense);
    return *this;
}
